from collections import defaultdict
from datetime import datetime
import pandas as pd


class ActionDetector:
    def __init__(self, df, window_size=5):
        self.df = df.copy()
        self.window_size = window_size  # 用于滑动窗口检测

    def preprocess(self, func_list, time_list=[]):
        """预处理数据，包括时间转换和单位转换"""

        # 转换时间列
        feature_dict = defaultdict(list)
        self.df['csvTime'] = pd.to_datetime(self.df['csvTime'])
        self.df = self.df.sort_values('csvTime')
        self.df['csvTime2'] = self.df['csvTime'].dt.strftime('%Y-%m-%d %H:%M:%S')

        # 使用 rolling 方法来创建滑动窗口
        # self.df.set_index('csvTime', inplace=True)
        self.df.reset_index(inplace=True)
        windows = self.df.rolling(window=self.window_size)

        # 存储满足条件的窗口的索引
        # valid_indices = set()
        valid_indices = []
        for inx, time_str in zip(self.df.index, self.df['csvTime2']):
            if time_str[:-3] in time_list:
                valid_indices.extend([inx - 2, inx - 1, inx, inx + 1, inx + 2])
        valid_indices = set(valid_indices)

        print('添加所有的列。', len(valid_indices))

        # 处理每个窗口
        for window_index, window in enumerate(windows):
            if len(window.dropna()) == self.window_size:
                for func in func_list:
                    sign, text = func(window)
                    if sign:
                        valid_indices.update(window.index)
                        feature_dict[list(window.index)[self.window_size // 2]].append(text)

        self.df['特征'] = ''
        for key, value in feature_dict.items():
            # if key in df.index:
            self.df.at[key, '特征'] = ','.join(value)
        # 根据索引去重并保留满足条件的窗口
        result_df = self.df.loc[sorted(valid_indices)].reset_index()
        return result_df


def process_data(json_input):
    # 解析JSON输入
    data = json_input["数据"]
    start_time = datetime.strptime(json_input["时间"]["开始"], "%Y-%m-%d %H:%M:%S")
    end_time = datetime.strptime(json_input["时间"]["结束"], "%Y-%m-%d %H:%M:%S")

    # 初始化一个空的DataFrame用于合并
    merged_df = None

    # 处理每个表
    for file_key, columns in data.items():
        # 读取CSV文件并选择指定列
        file_path = f'./data/{file_key}.csv'
        df = pd.read_csv(file_path, usecols=columns + ["csvTime"])

        # 将csvtime列转换为datetime类型
        df['csvTime'] = pd.to_datetime(df['csvTime'])

        # 将csvtime只保留到分钟部分
        df['csvTime'] = df['csvTime'].dt.strftime('%Y-%m-%d %H:%M')

        # 如果需要将csvTime转换回datetime类型
        df['csvTime'] = pd.to_datetime(df['csvTime'], format='%Y-%m-%d %H:%M')

        # 如果merged_df是None，直接赋值
        if merged_df is None:
            merged_df = df
        else:
            # 按照csvtime列进行连接
            merged_df = pd.merge(merged_df, df, on='csvTime', how='inner')

    if merged_df is not None:
        # 筛选出在指定时间范围内的数据
        filtered_df = merged_df[(merged_df['csvTime'] >= start_time) & (merged_df['csvTime'] <= end_time)]

        # 按照时间顺序排序
        sorted_df = filtered_df.sort_values(by='csvTime')
        return sorted_df
    else:
        # 如果没有数据进行合并，返回一个空的DataFrame
        return pd.DataFrame()


def detect_AjiaPowerON(window):
    try:
        conditions = [
            window.iloc[0]['Ajia-3_v'] == 'error' or window.iloc[0]['Ajia-5_v'] == 'error',
            window.iloc[1]['Ajia-3_v'] == 'error' or window.iloc[1]['Ajia-5_v'] == 'error',
            float(window.iloc[2]['Ajia-3_v']) >= 0 or float(window.iloc[2]['Ajia-5_v']) >= 0,
            float(window.iloc[3]['Ajia-3_v']) >= 0 or float(window.iloc[3]['Ajia-5_v']) >= 0,
            float(window.iloc[4]['Ajia-3_v']) >= 0 or float(window.iloc[4]['Ajia-5_v']) >= 0,
        ]
        return all(conditions), '`A架开机`特征行'
    except Exception as e:
        return False, ''


def detect_AjiaPowerOFF(window):
    try:
        conditions = [

            float(window.iloc[0]['Ajia-3_v']) >= 0 and float(window.iloc[0]['Ajia-5_v']) >= 0,
            float(window.iloc[1]['Ajia-3_v']) >= 0 and float(window.iloc[1]['Ajia-5_v']) >= 0,
            window.iloc[2]['Ajia-3_v'] == 'error' and window.iloc[2]['Ajia-5_v'] == 'error',
            window.iloc[3]['Ajia-3_v'] == 'error' and window.iloc[3]['Ajia-5_v'] == 'error',
            window.iloc[4]['Ajia-3_v'] == 'error' and window.iloc[4]['Ajia-5_v'] == 'error',
        ]
        return all(conditions), '`A架关机`特征行'
    except Exception as e:
        return False, ''


def detect_ONDP(window):
    try:
        conditions = [
            float(window.iloc[0]['P3_33']) == 0 or float(window.iloc[0]['P3_18']) == 0,
            float(window.iloc[1]['P3_33']) == 0 or float(window.iloc[1]['P3_18']) == 0,
            float(window.iloc[2]['P3_33']) > 0 or float(window.iloc[2]['P3_18']) > 0,
            float(window.iloc[3]['P3_33']) > 0 or float(window.iloc[3]['P3_18']) > 0,
            float(window.iloc[4]['P3_33']) > 0 or float(window.iloc[4]['P3_18']) > 0,
        ]
        return all(conditions), '`ON DP `特征行'
    except Exception as e:
        return False, ''


def detect_OFFDP(window):
    try:
        conditions = [
            float(window.iloc[0]['P3_33']) > 0 or float(window.iloc[0]['P3_18']) > 0,
            float(window.iloc[1]['P3_33']) > 0 or float(window.iloc[1]['P3_18']) > 0,
            float(window.iloc[2]['P3_33']) == 0 or float(window.iloc[2]['P3_18']) == 0,
            float(window.iloc[3]['P3_33']) == 0 or float(window.iloc[3]['P3_18']) == 0,
            float(window.iloc[4]['P3_33']) == 0 or float(window.iloc[4]['P3_18']) == 0,
        ]
        return all(conditions), '`OFF DP`特征行'
    except Exception as e:
        return False, ''


def detect_ONZBDC(window):
    '''判断折臂吊车开机'''
    try:
        conditions = [
            float(window.iloc[0]['13-11-6_v']) == 0,
            float(window.iloc[1]['13-11-6_v']) == 0,
            float(window.iloc[2]['13-11-6_v']) > 0,
            float(window.iloc[3]['13-11-6_v']) > 0,
            float(window.iloc[4]['13-11-6_v']) > 0,
        ]
        return all(conditions), '`折臂吊车开机`特征行'
    except Exception as e:
        return False, ''


def detect_OFFZBDC(window):
    '''判断折臂吊车开机'''
    try:
        conditions = [
            float(window.iloc[0]['13-11-6_v']) > 0,
            float(window.iloc[1]['13-11-6_v']) > 0,
            float(window.iloc[2]['13-11-6_v']) == 0,
            float(window.iloc[3]['13-11-6_v']) == 0,
            float(window.iloc[4]['13-11-6_v']) == 0,
        ]
        return all(conditions), '`折臂吊车关机`特征行'
    except Exception as e:
        return False, ''


def detect_check_xiaoting(window):
    '''判断小艇检查完毕或者小艇入水'''
    try:
        conditions = [
            True,
            True,
            float(window.iloc[2]['13-11-6_v']) > 15 and float(window.iloc[2]['13-11-6_v']) > float(
                window.iloc[1]['13-11-6_v']) and float(window.iloc[2]['13-11-6_v']) > float(
                window.iloc[3]['13-11-6_v']),
            True,
            True,
        ]
        return all(conditions), '折臂吊车动作，数值增加（回落前的最后一个值）,对应`小艇检查完毕`,`小艇入水`,`小艇落座`特征行'
    except Exception as e:
        return False, ''


def detect_zhengfuzheqidiao(window):
    '''征服者起吊'''
    try:
        conditions = [
            60 >= float(window.iloc[0]['Ajia-3_v']) >= 50 or 60 >= float(window.iloc[0]['Ajia-5_v']) >= 50,
            60 >= float(window.iloc[1]['Ajia-3_v']) >= 50 or 60 >= float(window.iloc[1]['Ajia-5_v']) >= 50,
            180 >= float(window.iloc[2]['Ajia-3_v']) > 60 or 180 >= float(window.iloc[2]['Ajia-5_v']) > 60,
            180 >= float(window.iloc[3]['Ajia-3_v']) >= 70 or 180 >= float(window.iloc[3]['Ajia-5_v']) >= 70,
            180 >= float(window.iloc[4]['Ajia-3_v']) >= 70 or 180 >= float(window.iloc[4]['Ajia-5_v']) >= 70,
        ]
        return all(conditions), '`征服者起吊`,`征服者出水`特征行,下放阶段为征服者起吊，回收阶段为征服者出水'
    except Exception as e:
        return False, ''


def detect_lanshengjiechu(window):
    '''A架最后一次工作'''
    try:
        conditions = [
            170 >= float(window.iloc[0]['Ajia-3_v']) >= 60 or 170 >= float(window.iloc[0]['Ajia-5_v']) >= 60,
            170 >= float(window.iloc[1]['Ajia-3_v']) >= 65 or 170 >= float(window.iloc[1]['Ajia-5_v']) >= 65,
            60 >= float(window.iloc[2]['Ajia-3_v']) >= 50 or 60 >= float(window.iloc[2]['Ajia-5_v']) >= 50,
            60 >= float(window.iloc[3]['Ajia-3_v']) >= 50 or 60 >= float(window.iloc[3]['Ajia-5_v']) >= 50,
            60 >= float(window.iloc[4]['Ajia-3_v']) >= 50 or 60 >= float(window.iloc[4]['Ajia-5_v']) >= 50,
        ]
        return all(conditions), 'A架从高值回落稳定，如果是下放阶段，为`缆绳解除`特征行，前一分钟为:`征服者入水`，如果是回收阶段，为`征服者落座`特征行。'
    except Exception as e:
        return False, ''


def detect_ajiabaihui(window):
    try:
        conditions = [
            float(window.iloc[0]['Ajia-3_v']) < float(window.iloc[2]['Ajia-3_v']),
            float(window.iloc[1]['Ajia-3_v']) < float(window.iloc[2]['Ajia-3_v']),
            float(window.iloc[2]['Ajia-3_v']) >= 70 or float(window.iloc[2]['Ajia-5_v']) >= 70,
            float(window.iloc[3]['Ajia-3_v']) < float(window.iloc[2]['Ajia-3_v']),
            float(window.iloc[4]['Ajia-3_v']) < float(window.iloc[2]['Ajia-3_v']),
        ]
        return all(conditions), '`A架摆回`,`A架摆出`特征行，征服者入水后，为摆回，征服者起吊前，为摆出'
    except Exception as e:
        return False, ''


detect_list = [detect_AjiaPowerON,
               detect_ONDP,
               detect_ONZBDC,
               detect_OFFZBDC,
               detect_check_xiaoting,
               detect_zhengfuzheqidiao,
               detect_lanshengjiechu,
               detect_ajiabaihui,
               detect_OFFDP,
               detect_AjiaPowerOFF,
               ]

# detector = ActionDetector(df)

# df2 = detector.preprocess()
